﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;

using Win32 = RemoteScriptingLibrary.Microsoft.Win32.Win32;

using Timer = System.Windows.Forms.Timer;
namespace RemoteScriptingLibrary
{


    public class ProcessHelper
    {
        private const int MAXWAIT = 50;

        private static Timer tKill = new Timer();
        private static Process P = null;
        private static int i = 0;

        public static Process GetProcessByPartialName(string _sProcessName)
        {
            Process[] aProcess = Process.GetProcesses();
            foreach (Process process in aProcess)
            {
                if (process.ProcessName.StartsWith(_sProcessName))
                {
                    return process;
                }
            }
            return null;
        }

        public static bool Kill(Process Proc)
        {
            //prevents deleting of the referenced object
            P = Process.GetProcessById(Proc.Id);
            try
            {
                P.CloseMainWindow();
            }
            catch
            {
                //There is no Window to close wo we kill it instantly.
                i = MAXWAIT;
            }
            tKill.Start();
            //label1.Text = "Killing PID: " + P.Id.ToString();
            return true;
        }

        //public static int ReadInt32(IntPtr hProcess, uint dwAddress)
        //{

        //    byte[] buffer = new byte[4];
        //    int bytesread;

        //    //Microsoft.Win32.Win32.ReadProcessMemory(hProcess, dwAddress, buffer, 4, out bytesread);
        //    return BitConverter.ToInt32(buffer, 0);

        //}

        //public static void WriteStructureToProcessMemory(IntPtr processHandle, IntPtr BaseAddress)
        //{
        //    UInt32 sizeOfLVITEM = (UInt32)Marshal.SizeOf(typeof(Win32.LVITEM));
        //    IntPtr ptrToLvItem = Marshal.AllocHGlobal((int)sizeOfLVITEM);
        //    Marshal.StructureToPtr(lvItem, ptrToLvItem, true);

        //    Win32.WriteProcessMemory(processHandle, BaseAddress, ptrToLvItem, sizeOfLVITEM, UIntPtr.Zero);
        //}

        private static void tKill_Tick(object sender, EventArgs e)
        {
            lock (P)
            {
                //This might not seem to be nice, but it is required.
                //The process can be terminated and race conditions can happen.
                try
                {
                    if (P.HasExited)
                    {
                        ExitSilent();
                    }
                    else if (P.WaitForInputIdle(0))
                    {
                        //btnAbort.Visible = btnKill.Visible = true;
                        //if (!focused)
                        {
                            //this.BringToFront();
                            //this.Focus();
                            //focused = true;
                        }
                        //label1.Text = "PROCESS WAITS FOR USER INPUT";
                    }
                    else
                    {
                        //btnAbort.Visible = btnKill.Visible = false;
                        //label1.Text = "Killing PID: " + P.Id.ToString();
                    }
                    if (++i > MAXWAIT)
                    {
                        if (!P.HasExited)
                        {
                            if (!P.WaitForInputIdle(0))
                            {
                                tKill.Stop();
                                KillExit();
                            }
                        }
                        else
                        {
                            ExitSilent();
                        }
                    }
                }
                catch
                {
                    ExitSilent();
                }
            }
        }

        private static void KillExit()
        {
            if (!P.HasExited)
            {
                P.Kill();
                //Close();
            }
        }

        private static void ExitSilent()
        {
            tKill.Stop();
            //Close();
        }
    }
}
